package simplecontext

import (
	"context"
	"fmt"
	"log"
	"sync"
	"time"
)

func use_ctx_chan() {
	// 设置超时时间为 2 秒
	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	defer cancel()

	// 错误通道，用于传递任务错误
	errChan := make(chan error, 1)

	var wg sync.WaitGroup

	// 启动三个任务
	taskNames := []string{"task1", "task2", "task3"}
	for _, taskName := range taskNames {
		wg.Add(1)
		go monitorTask(ctx, taskName, errChan, &wg)
	}

	// 监听错误和完成状态
	go func() {
		select {
		case err := <-errChan: // 如果有任务出错
			log.Printf("Error occurred: %v\n", err)
			cancel() // 取消所有任务执行
		case <-ctx.Done(): // 超时或手动取消
		}
	}()

	wg.Wait()

	// 检查是否超时
	if ctx.Err() == context.DeadlineExceeded {
		log.Println("Tasks terminated due to timeout")
	} else {
		log.Println("All tasks completed or canceled")
	}
}

// 定义任务执行函数
func monitorTask(ctx context.Context, name string, errChan chan error, wg *sync.WaitGroup) {
	defer wg.Done()

	// 每个任务只执行一次
	taskDone := false

	// 模拟任务分步执行
	step := 500 * time.Millisecond
	ticker := time.NewTicker(step)
	defer ticker.Stop()

	for {
		select {
		case <-ctx.Done(): // 上下文被取消
			if !taskDone {
				fmt.Printf("Task %s was canceled due to timeout or error: %v\n", name, ctx.Err())
			}
			return
		case <-ticker.C: // 模拟分步处理
			if taskDone {
				return // 如果任务已经完成，则直接返回，避免重复执行
			}

			// 模拟任务执行
			switch name {
			case "task1":
				// task1: 模拟处理时间为 2 秒
				time.Sleep(2 * time.Second)
				fmt.Printf("%s completed successfully\n", name)
				taskDone = true
			case "task2":
				// task2: 模拟出错
				errChan <- fmt.Errorf("%s encountered an error", name)
				taskDone = true
			case "task3":
				// task3: 模拟长时间执行，超时后取消
				time.Sleep(4 * time.Second)
				if ctx.Err() == nil { // 确保没有超时
					fmt.Printf("%s completed successfully\n", name)
				} else {
					fmt.Printf("%s was canceled due to timeout or err:%v\n", name, ctx.Err())
				}

				taskDone = true
			}
		}
	}
}
